/*
 * File: interp.c
 * --------------
 * This program simulates the top level of a programming
 * language interpreter.  The program reads an expression,
 * evaluates the expression, and displays the result.
 */

#include <stdio.h>
#include "genlib.h"
#include "exception.h"
#include "strlib.h"
#include "simpio.h"
#include "exp.h"
#include "sexp.h"
#include "eval.h"
#include "parser.h"
#include "scanadt.h"

static void printSExp(sExpADT exp);

/* Main program */

main()
{
    scannerADT scanner;
    expressionADT exp;
	sExpADT sx;
    string line, token;
    int value;

	printf("Expression interpreter (type \"quit\" to exit)\n\n");

    InitVariableTable();
    scanner = NewScanner();
    SetScannerSpaceOption(scanner, IgnoreSpaces);
    while (TRUE) {
        try {
            printf("=> ");
            line = GetLine();
            if (StringEqual(line, "quit")) exit(0);
            SetScannerString(scanner, line);

			token = ReadToken(scanner);
			if(StringEqual(token, ":"))
			{
				InitSymbolTable();
				sx = ParseSExp(scanner);
				printSExp(sx);
			}
			else
			{
				SaveToken(scanner, token);

				exp = ParseExp(scanner);
				value = EvalExp(exp);
				printf("%d\n", value);
			}

          except(ErrorException)
            printf("Error: %s\n", (string) GetExceptionValue());
        } endtry
    }
}

static void printSExp(sExpADT sx)
{	
	if(SExpType(sx) != DtprType)
	{
		if(SExpType(sx) == NumberType)
			printf("%d", SExpToNumber(sx));
		else if(SExpType(sx) == AtomType)
			printf("%s", AtomToString(sx));
		else
			Error("S-expression does not have a valid type.");
	}
	else
	{
		if(SExpType(Car(sx)) == DtprType)
		{
			printf("(");
		}
		printSExp(Car(sx));

		if(Cdr(sx) == NIL)
			printf(")");
		else
			printSExp(Cdr(sx));
	
	}
}
